package com.lee.commonerror.code.concurrent;

import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StopWatch;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * {@link CopyOnWriteArrayList} 使用的时候应该注意场景,用于读多写少
 * @author ：liylw
 * @date ：Created in 2021/4/12 15:47
 */
@Slf4j
@RestController
@RequestMapping("CopyOnWriteArrayListDemo")
public class CopyOnWriteArrayListDemo {

    /**
     * {@link CopyOnWriteArrayList} 与 {@code Collections.SynchronizedList} 写入性能对比
     * @return
     */
    @GetMapping("write")
    public Map<String,Integer> testWrite(){
        List<Integer> copyOnWriteArrayList = new CopyOnWriteArrayList<>();
        List<Integer> synchronizedList = Collections.synchronizedList(new ArrayList<>());
        StopWatch stopWatch = new StopWatch();
        int loopCount = 100_000;
        stopWatch.start("Write:copyOnWriteArrayList");
        IntStream.rangeClosed(1,loopCount).parallel()
                .forEach(i -> copyOnWriteArrayList.add(ThreadLocalRandom.current().nextInt(loopCount) ));
        stopWatch.stop();

        stopWatch.start("Write:synchronizedList");
        IntStream.rangeClosed(1,loopCount).parallel()
                .forEach(i -> synchronizedList.add(ThreadLocalRandom.current().nextInt(loopCount)));
        stopWatch.stop();

        log.info(stopWatch.prettyPrint());
        Map<String ,Integer> result = new HashMap<>(2);
        result.put("copyOnWriteArrayList",copyOnWriteArrayList.size());
        result.put("synchronizedList",synchronizedList.size());
        return result;
    }


    /**
     * 填充list
     * @param list
     */
    private void addAll(List<Integer> list){
        list.addAll(IntStream.rangeClosed(1,1_000_000).boxed().collect(Collectors.toList()));
    }


    /**
     * {@link CopyOnWriteArrayList} 与 {@code Collections.SynchronizedList} 读取性能对比
     * @return
     */
    @GetMapping("read")
    public Map<String ,Integer> testRead(){
        List<Integer> copyOnWriteArrayList = new CopyOnWriteArrayList<>();
        List<Integer> synchronizedList = Collections.synchronizedList(new ArrayList<>());

        addAll(copyOnWriteArrayList);
        addAll(synchronizedList);
        StopWatch stopWatch = new StopWatch();
        int loopCount = 1_000_000;
        int count = copyOnWriteArrayList.size();
        stopWatch.start("Read:copyOnWriteArrayList");
        IntStream.rangeClosed(1,loopCount).parallel().forEach(i-> copyOnWriteArrayList.get(ThreadLocalRandom.current().nextInt(count)));
        stopWatch.stop();
        stopWatch.start("Read:synchronizedList");
        IntStream.range(0,loopCount).parallel().forEach(i-> synchronizedList.get(ThreadLocalRandom.current().nextInt(count)));
        stopWatch.stop();

        log.info(stopWatch.prettyPrint());

        Map<String,Integer> result = new HashMap<>();
        result.put("copyOnWriteArrayList",copyOnWriteArrayList.size());
        result.put("synchronizedList",synchronizedList.size());
        return result;
    }

}
